#include <iostream>
#include <functional>
using namespace std;

template<typename>
//主版本，优先级最低, 定义数据类型成员type：函数类型 void(int)
struct remove_class_type { using type = void(int); }; 
//特化版本一: 模板实参为成员函数指针，定义type为成员函数的函数类型
template<typename C, typename R, typename... ArgTypes>
struct  remove_class_type<R (C::*)(ArgTypes...)> { using type = R(ArgTypes...); };
/*特化版本二: 模板实参为const成员函数指针，定义type为成员函数去掉const修饰后的
 *的函数类型*/
template<typename C, typename R, typename... ArgTypes>
struct remove_class_type<R (C::*)(ArgTypes...) const> { using type = R(ArgTypes...); };

template <typename L>
class call_sig_helper  { //获取函数对象类L的operator()重载函数的指针类型
    //函数模板
    template <typename L1, typename ...Args> 
        //L1::operator() 必须是公有的: public
        static decltype(&L1::operator()) test(int); 
    //函数模板重载(匹配限制更少，优先级低)
    template <typename L1> 
        static void test(...); 
public:
    /*如果L为函数对象类型(重载了operator()), 则匹配第一个模板, type为L的成员函数
     *指针，指向operator()运算符重载函数, 否则type为void类型*/
    using type = decltype(test<L>(0));
};

//主模板，获取函数对象类L的调用特征
template <typename L>
struct call_signature : public remove_class_type<typename call_sig_helper<L>::type> {};
//特化模板: 获取普通函数类型的调用特征
template <typename R, typename... ArgTypes> 
struct call_signature<R (ArgTypes...)> { using type = R (ArgTypes...); };
//特化模板: 获取函数指针的调用特征
template <typename R, typename... ArgTypes>
struct call_signature<R (*)(ArgTypes...)> { using type = R (ArgTypes...); };
//特化模板: 获取成员函数指针的调用特征
template <typename C, typename R, typename... ArgTypes>
struct call_signature<R (C::*)(ArgTypes...)> { using type = R (ArgTypes...); };
//特化模板: 获取const成员函数指针的调用特征
template<typename C, typename R, typename... ArgTypes>
struct call_signature<R (C::*)(ArgTypes...) const>  { using type = R(ArgTypes...); };
//主模板：值为否
template <typename> struct is_valid_signature : public std::false_type {};
//特化模板：当模板参数类型为void (Arg)时返回真
template <typename Arg>
struct is_valid_signature<void (Arg)> : public std::true_type {};

int tf1(void) { return 0;}
void tf2(int d) { cout << "function void tf2(int) is called" << "data:" << d << '\n'; }
struct Functor {
    void operator()(char d) { cout<<"void Functor::operator()(char) is called" << "data:" << d << '\n';}
};

auto lf = [](char *d)->void{ 
    cout << "lambda [](char *)->void is called" << "data:" << d << '\n';
};

//函数模板：返回false，如果由于T1的调用特征不满足导致，则提示输出
template <typename T1, typename T2> 
bool call_functor(T1 arg1, T2 arg2) {
    if(!is_valid_signature<typename call_signature<T1>::type>::value)
        cout << "func need callable (lambda, *function, callable obj) (Args...) -> void" << '\n';
    return false;
}
//重载函数模板(模板参数少，优先级更高)：返回true。如果func调用特征满足，则调用
//func。
template<typename F>
bool call_functor(F func, void *d) {
    if(is_valid_signature<typename call_signature<F>::type>::value)
        func(*static_cast<typename std::function<typename call_signature<F>::type>::argument_type *>(d));
    return true;
} 


int main(void)
{
    int n = 1;
    char c = 'F';
    const char *s = "lambda callable obj";
    call_functor(tf1, (void*)0);
    call_functor(tf2, (void*)&n);
    call_functor(Functor(), (void*)&c);
    call_functor(lf, (void*)&s);

    return 0;
}
